/*******************************************************************************
*
*
*	这是一个关于TCP协议传输数据的服务器程序，目的是接收客户端的连接，并把客户端
*	发送的数据输出到终端
*
* 	注意：使用TCP协议的过程中，服务器的程序流程如下
*
*
*  	1.创建套接字	socket
*  	2.绑定端口号	bind
*  	3.监听客户端	listen
*  	4.接受客户端    accept
*  	5.数据的收发	recv & send
*  	6.关闭服务器	close
*
* 	注意：服务器的端口号必须要和客户端使用的一致，否则无法顺利接受数据，另外运
* 	行程序的时候需要确保服务器和客户端处于同一个网络
*
* *****************************************************************************/
#include "Project.h"
#include <errno.h>
#include <signal.h>

// 服务器配置
#define SERVER_PORT 6666
#define MAX_CLIENTS 5
#define BUFFER_SIZE 1024
#define MAX_RETRIES 3
#define CONNECTION_TIMEOUT 30

// 全局变量
static int server_sock_fd = -1;
static volatile int server_running = 1;


// 信号处理函数
void signal_handler(int sig) {
    if (sig == SIGINT || sig == SIGTERM) {
        printf("收到退出信号，正在关闭服务器...\n");
        server_running = 0;
        if (server_sock_fd != -1) {
            close(server_sock_fd);
            server_sock_fd = -1;
        }
    }
}

// 处理客户端连接
int handle_client_connection(int client_fd, struct sockaddr_in *client_addr) {
    char recv_buf[BUFFER_SIZE] = {0};
    ssize_t bytes_received;
    int retry_count = 0;
    
    printf("客户端连接: %s:%d\n", 
           inet_ntoa(client_addr->sin_addr), 
           ntohs(client_addr->sin_port));
    
    while (server_running && retry_count < MAX_RETRIES) {
        memset(recv_buf, 0, sizeof(recv_buf));
        
        // 设置接收超时
        struct timeval timeout;
        timeout.tv_sec = CONNECTION_TIMEOUT;
        timeout.tv_usec = 0;
        setsockopt(client_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
        
        bytes_received = recv(client_fd, recv_buf, sizeof(recv_buf) - 1, 0);
        
        if (bytes_received < 0) {
            if (errno == EAGAIN || errno == EWOULDBLOCK) {
                printf("接收超时\n");
                retry_count++;
                continue;
            } else {
                printf("接收数据失败: %s\n", strerror(errno));
                break;
            }
        } else if (bytes_received == 0) {
            printf("客户端断开连接\n");
            break;
        }
        
        recv_buf[bytes_received] = '\0'; // 确保字符串结束
        printf("接收到数据: %s\n", recv_buf);
        
        // 处理学生身份识别
        if (strstr(recv_buf, "student") != NULL) {
            printf("识别为学生身份\n");
            read_JPEG_file("student_ways.jpg", 0, 0);
            
            // 使用互斥锁保护状态修改
            pthread_mutex_lock(&state_mutex);
            desk = 0;               // 不在桌面了
            teacher_ways_flag = 0;  // == 1 就是老师
            student_ways_flag = 1;  // == 1 就是学生
            stu_atten_flag = 0;     // 学生打卡方式   1蓝牙 2刷卡  3人脸  4密码
            tea_atten_flag = 0;     // 老师打卡方式   1蓝牙 2刷卡  3人脸  4密码
            again_re_select_flag = 0; // 失败了显示
            pthread_mutex_unlock(&state_mutex);
            
            return 1; // 成功处理
        }
        
        // 处理教师身份识别
        if (strstr(recv_buf, "teacher") != NULL) {
            printf("识别为教师身份\n");
            read_JPEG_file("teacher_ways.jpg", 0, 0);
            
            // 使用互斥锁保护状态修改
            pthread_mutex_lock(&state_mutex);
            desk = 0;               // 不在桌面了
            teacher_ways_flag = 1;  // == 1 就是老师
            student_ways_flag = 0;  // == 1 就是学生
            stu_atten_flag = 0;     // 学生打卡方式   1蓝牙 2刷卡  3人脸  4密码
            tea_atten_flag = 0;     // 老师打卡方式   1蓝牙 2刷卡  3人脸  4密码
            again_re_select_flag = 0; // 失败了显示
            pthread_mutex_unlock(&state_mutex);
            
            return 1; // 成功处理
        }
        
        // 发送确认响应
        const char *response = "OK";
        if (send(client_fd, response, strlen(response), 0) < 0) {
            printf("发送响应失败: %s\n", strerror(errno));
        }
        
        retry_count = 0; // 重置重试计数
    }
    
    return 0; // 处理失败或超时
}

void *server_start(void* arg)
{
    struct sockaddr_in my_addr, client_addr;
    socklen_t client_len;
    int client_fd;
    
    // 设置信号处理
    signal(SIGINT, signal_handler);
    signal(SIGTERM, signal_handler);
    
    // 1.创建socket套接字 IPV4 TCP协议
    server_sock_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_sock_fd == -1) {
        printf("创建socket失败: %s\n", strerror(errno));
        return NULL;
    }
    
    // 设置socket选项，允许地址重用
    int opt = 1;
    if (setsockopt(server_sock_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
        printf("设置socket选项失败: %s\n", strerror(errno));
        close(server_sock_fd);
        return NULL;
    }

    // 2.套接字socket绑定端口
    memset(&my_addr, 0, sizeof(my_addr));
    my_addr.sin_family = AF_INET;
    my_addr.sin_port = htons(SERVER_PORT);
    my_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(server_sock_fd, (struct sockaddr *)&my_addr, sizeof(my_addr)) < 0) {
        printf("绑定端口失败: %s\n", strerror(errno));
        close(server_sock_fd);
        return NULL;
    }

    // 3.服务器开始侦听
    if (listen(server_sock_fd, MAX_CLIENTS) < 0) {
        printf("监听失败: %s\n", strerror(errno));
        close(server_sock_fd);
        return NULL;
    }
    
    printf("服务器启动成功，监听端口: %d\n", SERVER_PORT);

    // 4.接受客户端连接并处理
    while (server_running) {
        client_len = sizeof(client_addr);
        client_fd = accept(server_sock_fd, (struct sockaddr *)&client_addr, &client_len);
        
        if (client_fd < 0) {
            if (server_running) {
                printf("接受连接失败: %s\n", strerror(errno));
            }
            continue;
        }
        
        // 处理客户端连接
        handle_client_connection(client_fd, &client_addr);
        
        // 关闭客户端连接
        close(client_fd);
    }

    // 6.关闭套接字
    if (server_sock_fd != -1) {
        close(server_sock_fd);
        server_sock_fd = -1;
    }
    
    printf("服务器已关闭\n");
    return NULL;
}